// pages/workbench/workbench.js

import { menuList } from './fakeData.js'

// 拖拽相关 start
let baseXY = {
      x: 0,
      y: 0,
    },
    tStart = {
      x: 0,
      y: 0,
    },
    // 拖拽盒子的高宽，计算盒子中心位置
    moveBox = {
      width: 0,
      height: 0,
    },
    // 滑块滑动时的位置
    curIdx = 0,
    // 拖拽后应用新顺序
    aftDragOrder = []
// 拖拽相关 end

Page({

  /**
   * 页面的初始数据
   */
  data: {
    isEdit: false,

    navList: [
      { src: '../../image/workbench1/chunabiao.png', name: '出纳表', url: '/accounting/cashier_table/cashier_table?entity=all_cashier', },
      { src: '../../image/workbench1/chakanpingzheng.png', name: '查看凭证', url: '/accounting/accounting_voucher/accounting_voucher?entity=all_voucher', },
      { src: '../../image/workbench1/kehuxinxi.png', name: '客户信息', url: '/pages/general_entity/general_entity?entity=customer', },
      { src: '../../image/workbench1/chanpinkucun.png', name: '产品库存', url: '/stock/stock_balance/stock_balance', },
    ],
    appList: [],
    // 参考的appList
    referAppList: [],
    blankAppList: [],
    menuList: [],

    menuHide: true,

    // 拖拽相关参数 start
    moveW: 0,
    moveH: 0,
    moveX: 0,
    moveY: 0,
    canDrag: false,
    dragEnd: false,
    selectedMoveIdx: null,
    selectedMoveItem: null,
    // 拖拽相关参数 end

  },

  // nav 跳转
  navTo(e) {
    if(this.data.isEdit) return
    let url = e.currentTarget.dataset.url
    if(!url) {
      wx.$toast('小程序不支持该功能！')
      return
    } else if(url === 'more') {
      return
    }
    wx.navigateTo({
      url,
    })
  },
  // 编辑
  toggleEdit() {
    let { isEdit, appList, menuList, } = this.data
    if(!appList.length || !menuList.length) return
    if(isEdit) {  // 保存
      this.setData({
        isEdit: false,
      })
      this.saveAppSet()
    } else {  // 开启编辑
      this.setData({
        isEdit: true,
      })
    }
  },
  // 移除
  reduceApp(e) {
    let i = e.currentTarget.dataset.i

    this.showModal('确认移除', '确定将该应用移除出首页应用？', () => {
      let { appList, menuList, } = this.data,
          rows = JSON.parse(JSON.stringify(appList))
      appList.forEach((item, idx) => {
        if(idx > i) {
          item.basetop = item.top = rows[idx - 1].top
          item.baseleft = item.left = rows[idx - 1].left
        }
      })
      let delItem = appList.splice(i, 1)[0]

      menuList.some(menu => {
        let parentId = delItem.parentId
        if(![null, undefined].includes(delItem.grandParentId)) parentId = delItem.grandParentId

        if(parentId === menu.menuId) {
          menu.children.some(child => {
            if(delItem.menuId === child.menuId) {
              child.hide = false
              return true
            }
          })
          if(menu.hide) menu.hide = false
          return true
        }
      })

      this.setData({
        appList,
        menuList,
      })
    })
  },
  // 增加
  addApp(e) {
    let { appList, blankAppList, menuList, } = this.data,
        lastIdx = appList.length - 1,
        d = e.currentTarget.dataset
    if(appList.length >= 10) {
      // this.showModal('请先移除首页应用', '首页应用最多可设置9个，请先进行移除再添加！')
      wx.$toast('已经加满了，试试换掉一个吧')
    } else {
      this.showModal('确认添加', '确定将该应用添加到首页应用？', () => {
        let menu = menuList[d.pid],
            childs = menu.children,
            addItem = { ...childs[d.i] }
        childs[d.i].hide = true
        let hideChild = childs.filter(c => c.hide)
        if(hideChild.length === childs.length) menu.hide = true

        addItem.top = blankAppList[lastIdx].top
        addItem.left = blankAppList[lastIdx].left

        appList[lastIdx].top = blankAppList[lastIdx + 1].top
        appList[lastIdx].left = blankAppList[lastIdx + 1].left

        appList.splice(lastIdx, 0, addItem)

        this.setData({
          appList,
          menuList,
        })
      })
    }
  },
  showModal(title, content, confirmFn) {
    wx.showModal({
      title: title || '',
      content: content || '',
      success: (res) => {
        if(res.confirm) {
          confirmFn && confirmFn()
        }
      },
    })
  },
  timeout(fn, time) {
    let timer = setTimeout(() => {
      fn && fn()
      clearTimeout(timer)
    }, time)
  },

  // 设置拖拽盒子的高宽
  setDragWidthHeight(e) {
    let query = wx.createSelectorQuery(),
        blankRows = []
    query.select('.move_wrap > .col_5').boundingClientRect(rect => {
      let { width, height, top, left, } = rect
      baseXY.x = left
      baseXY.y = top
      moveBox.width = width
      moveBox.height = height
      for(let i = 0, len = 10; i < len; i++) {
        let t = Math.floor(i / 3) * height,
            l = (i < 3 ? i : i - 3) * width
        if(!t) t = '0'
        if(!l) l = '0'
        blankRows.push({ top: t, left: l, })
      }
      this.setData({
        moveW: Math.ceil(width * 3),
        moveH: height * 2,

        blankAppList: blankRows,
      })
    }).exec()
  },

  // 拖拽相关 start
  /** 拖拽功能实现参考
   * https://www.cnblogs.com/gxLog/p/15876286.html 、 https://github.com/GXYOG/wxapp-drag
   * https://www.jb51.net/article/249044.htm
   * https://www.cnblogs.com/haha1212/p/11562944.html
   */
  touchStart(e) {
    if(this.notAllowDrag(e)) return
    let { offsetLeft, offsetTop } = e.currentTarget
    let d = e.currentTarget.dataset,
        selectedMoveItem = d.item
    this.setData({
      moveX: offsetLeft,
      moveY: offsetTop,
      selectedMoveItem,
    })
  },
  touchMove(e) {
    if(this.notAllowDrag(e) || !this.data.canDrag) return
    let x = e.changedTouches[0].pageX,
        y = e.changedTouches[0].pageY,
        moveX = baseXY.x + x - tStart.x,
        moveY = baseXY.y + y - tStart.y,
        centerX = moveX + moveBox.width / 2,
        centerY = moveY + moveBox.height / 2

    let { appList, blankAppList, } = this.data,
        appLen = appList.length
    appList.forEach((item, i) => {
      let xLeft = +(blankAppList[i].left),
          xRight = xLeft + moveBox.width,
          yTop = +(blankAppList[i].top),
          yBottom = yTop + moveBox.height
      if(centerX > xLeft && centerX < xRight && centerY > yTop && centerY < yBottom) {
        curIdx = i
      }
    })
    if(curIdx === appLen - 1) curIdx--;

    let befIdx = this.data.selectedMoveIdx
    aftDragOrder = [ ...(new Array(appLen)).keys() ]
    let delItem = aftDragOrder.splice(befIdx, 1)[0]
    aftDragOrder.splice(curIdx, 0, delItem)
    aftDragOrder.forEach((n, o) => {
      let item = appList[n],
          bItem = blankAppList[o]
      item.left = bItem.left
      item.top = bItem.top
    })

    this.setData({
      moveX: moveX,
      moveY: moveY,

      appList,
      referAppList: [ ...appList ],
    })
  },
  // touchMove: wx.$util.debounce(function(e) {
  //   if(this.notAllowDrag(e) || !this.data.canDrag) return
  //   let x = e.changedTouches[0].pageX,
  //       y = e.changedTouches[0].pageY,
  //       moveX = baseXY.x + x - tStart.x,
  //       moveY = baseXY.y + y - tStart.y,
  //       centerX = moveX + moveBox.width / 2,
  //       centerY = moveY + moveBox.height / 2

  //   let { appList, blankAppList, } = this.data,
  //       appLen = appList.length
  //   appList.forEach((item, i) => {
  //     let xLeft = +(blankAppList[i].left),
  //         xRight = xLeft + moveBox.width,
  //         yTop = +(blankAppList[i].top),
  //         yBottom = yTop + moveBox.height
  //     if(centerX > xLeft && centerX < xRight && centerY > yTop && centerY < yBottom) {
  //       curIdx = i
  //     }
  //   })
  //   if(curIdx === appLen - 1) curIdx--;

  //   let befIdx = this.data.selectedMoveIdx
  //   aftDragOrder = [ ...(new Array(appLen)).keys() ]
  //   let delItem = aftDragOrder.splice(befIdx, 1)[0]
  //   aftDragOrder.splice(curIdx, 0, delItem)
  //   aftDragOrder.forEach((n, o) => {
  //     let item = appList[n],
  //         bItem = blankAppList[o]
  //     item.left = bItem.left
  //     item.top = bItem.top
  //   })

  //   this.setData({
  //     moveX: moveX,
  //     moveY: moveY,

  //     appList,
  //     referAppList: [ ...appList ],
  //   })
  // }, 15),
  touchEnd(e) {
    if(this.notAllowDrag(e) || !this.data.canDrag) return
    let idx = this.data.selectedMoveIdx,
        appList = this.data.appList,
        moveItem = appList[idx],
        moveX = moveItem.left,
        moveY = moveItem.top
    this.setData({
      canDrag: false,
      dragEnd: true,
    })

    // 拖拽结束后，重新调整appList的顺序，重新调整顺序后，因为禁止就地复用，会闪一下
    let rows = []
    aftDragOrder.forEach(o => {
      let item = appList[o]
      rows.push(item)
    })

    this.timeout(() => {
      this.setData({
        moveX,
        moveY,
      })
    }, 0)
    this.timeout(() => {
      this.setData({
        appList: rows,
      })
    }, 140)
    this.timeout(() => {
      this.setData({
        dragEnd: false,
        selectedMoveIdx: null,
        referAppList: [ ...rows ],
      })
    }, 180)
  },
  // 长按开启拖拽
  longPress(e) {
    if(this.notAllowDrag(e)) return
    this.setData({
      selectedMoveIdx: e.currentTarget.dataset.i,
      canDrag: true,
    })

    let touches = e.changedTouches[0]
    tStart.x = touches.pageX
    tStart.y = touches.pageY
    baseXY.x = this.data.moveX
    baseXY.y = this.data.moveY
  },
  notAllowDrag(e) {
    let isMore = e.currentTarget.dataset.url === 'more'
    return !this.data.isEdit || isMore
  },
  // 拖拽相关 end


  // 接口
  // 获取首页应用列表
  getAppList() {
    wx.$post(3, 'Menu/query_menu_person_qx', {}).then(res => {
      if(res.errcode !== 0) return
      let rows = res.data.row
      wx.$parseUrl(rows)

      rows.sort((a, b) => a.sort - b.sort)
      rows.push({ menuName: '更多', menuLabel: '更多', menuURL: 'more', wxMenuURL: 'more', menuIcon: '../../image/workbench1/gengduo.png', },)

      let timer = setInterval(() => {
        let blankAppList = this.data.blankAppList
        if(blankAppList.length) {
          rows.forEach((item, i) => {
            let { top, left, } = blankAppList[i]
            item.top = top
            item.left = left
          })
          this.setData({
            appList: rows,
            referAppList: [ ...rows ],
          }, () => {
            this.hideMenu()
          })
          clearInterval(timer)
        }
      }, 100)
    })
  },
  // 获取菜单列表
  getMenuList() {
    wx.$post(3, 'Menu/query_menu_qx', {}).then(res => {
      if(res.errcode !== 0) return
      // 有三级菜单的话，并到二级菜单中
      let rows = res.data.row

      // 221029 一级菜单有url的话也要显示
      rows.forEach(row => {
        if(row.menuURL) {
          row.children = [{
            ...row,
            grandParentId: row.menuId,
          }]
          row.menuURL = ''
        }
      })

      wx.$parseUrl(rows)

      let filterRows = []
      rows.forEach(row => {
        if(row.children) {
          // 二级菜单
          let child = row.children.filter(c => c.menuURL)
          // 三级菜单，并到二级菜单中
          let l3Menu = row.children.filter(c => c.children && c.children.length)
          l3Menu.forEach(menu => {
            let grand = menu.children.filter(g => {
              if(g.menuURL) {
                g.grandParentId = row.menuId
                return true
              }
            })
            child.push(...grand)
          })
          if(child.length) {
            row.children = child
            filterRows.push(row)
          }
        }
      })
      this.setData({
        menuList: filterRows,
      })
      this.hideMenu()
    })
  },
  // 隐藏二级菜单中 已在首页应用显示 的菜单
  hideMenu() {
    let { appList, menuList, } = this.data
    if(!appList.length || !menuList.length) return

    menuList.some((menu, m) => {
      let mId = menu.menuId,
          menuChilds = menu.children,
          hasGrand = menuChilds.filter(grand => grand.grandParentId).length,  // 是否有三级菜单
          childHide = 0
      appList.some(app => {
        if(app.parentId) {  // 二级/三级菜单
          if(app.parentId === mId || hasGrand) {
            menuChilds.some((child, c) => {
              if(app.menuId === child.menuId) {
                child.hide = true
                menuChilds[c] = { ...child }
                childHide++
                if(child.grandParentId) app.grandParentId = child.grandParentId
                return true
              }
            })
          }
        } else if(app.parentId === 0) {  // 一级
          if(app.menuId === mId) {
            childHide++
            app.grandParentId = mId
            return true
          }
        }

      })
      if(childHide === menuChilds.length) menu.hide = true
    })

    this.setData({
      menuList,
      appList,
    }, () => {
      this.setData({
        menuHide: false,
      })
    })
  },
  // 保存首页应用设置
  saveAppSet() {
    let appList = this.data.appList,
        post = []
    appList.forEach((item, i) => {
      if(item.menuURL !== 'more') {
        let obj = { ...item, }
        delete obj.grandParentId
        delete obj.top
        delete obj.left
        delete obj.basetop
        delete obj.baseleft
        delete obj.wxMenuURL
        obj.sort = i
        post.push(obj)
      }
    })

    wx.showLoading({ mask: true, })
    wx.$post(3, 'Menu/update_all_menu_person', post).then(res => {
      if(res.errcode !== 0) return
      wx.$toast('保存成功')
    })
  },

  // 菜单栏打开收起
  toggleMenu(e){
    let {id} = e.currentTarget.dataset,
      {menuList} = this.data;
    menuList.map(menu =>{
      if (menu.menuId === id){
        menu.contentHide = !menu.contentHide
      }
    });
    this.setData({menuList})
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    wx.$setBarTitle();
    this.setDragWidthHeight()
    this.getAppList()
    this.getMenuList()
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  },
})
